package com.jwcao.common.cast.operation.injection;

import com.jwcao.common.cast.annotation.factory.CastSetFactory;
import com.jwcao.common.cast.operation.access.AccessOperation;
import com.jwcao.common.cast.operation.access.MethodAccessOperation;
import com.jwcao.common.cast.operation.access.field.CastFieldAccessOperation;
import com.jwcao.common.cast.operation.access.field.FieldAccessOperation;
import com.jwcao.common.scan.object.ScanClass;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;

/**
 * name: InjectionOperationFactory description: TODO
 *
 * @author caojingwei date: 2023/3/24 22:32
 */
public class InjectionOperationFactory {

    public static List<InjectionOperation> get(String id, ScanClass targetClass,
        List<AccessOperation> accessOperationList) {
        List<InjectionOperation> injectionOperationList = new ArrayList<>();

        //组装所有 set 方法的操作
        Method[] methods = targetClass.getClazz().getMethods();
        List<InjectionOperation> methodInjectionOperationList = Arrays.stream(methods).map(m -> {
            String[] argNames = CastSetFactory.get(id, m);
            if (ArrayUtils.isNotEmpty(argNames)){
                // 1. 从 AccessOperation 中搜索符合原名称，如果没有从 sourceClass 中新建补充
                List<AccessOperation> fieldAccessOperationList = Arrays.stream(argNames).map(name -> {
                    return accessOperationList.stream().filter(o -> o instanceof FieldAccessOperation)
                        .map(o -> (FieldAccessOperation) o)
                        .filter(o -> o.judgeInjectMethodParameter(name))
                        .findAny().orElse(null);
                }).collect(Collectors.toList());
                return new MethodInjectionOperation(targetClass, fieldAccessOperationList, m.getName());
            }
            return null;

        }).filter(Objects::nonNull).collect(Collectors.toList());

        injectionOperationList.addAll(methodInjectionOperationList);
        //组装所有的field对接
        List<InjectionOperation> fieldInjectionOperationList = accessOperationList.stream()
            .filter(o -> o instanceof CastFieldAccessOperation || o instanceof MethodAccessOperation)
            .map(f -> new FieldInjectionOperation(targetClass, f)).collect(Collectors.toList());


        injectionOperationList.addAll(fieldInjectionOperationList);
        return injectionOperationList;
    }
}
